import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import morgan from "morgan";
import ipRoutes from "./routes/ip2region.routes.js";
import czdbRoutes from "./routes/czdb.routes.js";
import errorHandler from "./middleware/error.middleware.js";
import czdbService from "./services/czdb.service.js";
import cron from "node-cron";
import updateCZDB from "../scripts/update-czdb.js";

// 获取当前文件的目录路径
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const rootDir = path.join(__dirname, "..");

// 加载环境变量
dotenv.config();

const app = express();
const port = process.env.PORT || 3000;

// 确保logs目录存在
const logsDir = path.join(rootDir, "logs");
if (!fs.existsSync(logsDir)) {
  fs.mkdirSync(logsDir);
}

// 创建一个写入流，用于记录访问日志
const accessLogStream = fs.createWriteStream(path.join(logsDir, "access.log"), {
  flags: "a",
});

// 自定义日志格式
morgan.token("ip-info", (req) => {
  const ip = req.ip || req.connection.remoteAddress;
  return `[IP: ${ip}]`;
});

morgan.token("error", (req, res) => {
  if (res.statusCode >= 400) {
    return ` [Error: ${res._error || "Unknown Error"}]`;
  }
  return "";
});

// 配置日志格式
const logFormat =
  ':ip-info [:date[iso]] ":method :url HTTP/:http-version" :status :response-time ms :error';

// 中间件
app.use(cors());
app.use(express.json());
// 控制台日志
app.use(morgan(logFormat));
// 文件日志
app.use(morgan(logFormat, { stream: accessLogStream }));

// 设置信任代理
app.set("trust proxy", true);

// 检查数据库文件是否存在
const checkDatabaseFiles = () => {
  const ipv4DbPath = process.env.CZDB_IPV4_PATH;
  const ipv6DbPath = process.env.CZDB_IPV6_PATH;

  if (!ipv4DbPath && !ipv6DbPath) {
    console.error("错误: 至少需要提供一个数据库文件路径");
    process.exit(1);
  }

  // 解析相对路径
  const resolveDbPath = (dbPath) => {
    if (!dbPath) return null;
    return dbPath.startsWith(".") ? path.resolve(rootDir, dbPath) : dbPath;
  };

  const resolvedIpv4Path = resolveDbPath(ipv4DbPath);
  const resolvedIpv6Path = resolveDbPath(ipv6DbPath);

  console.log("检查数据库文件路径:");
  console.log("IPv4路径:", resolvedIpv4Path);
  console.log("IPv6路径:", resolvedIpv6Path);

  const filesExist =
    (resolvedIpv4Path ? fs.existsSync(resolvedIpv4Path) : true) &&
    (resolvedIpv6Path ? fs.existsSync(resolvedIpv6Path) : true);

  return filesExist;
};

// CZDB相关功能只在启用时加载
const isCzdbEnabled = process.env.CZDB_ENABLED === "true";

  if (isCzdbEnabled) {
  console.log("CZDB功能已启用");

  // 初始化CZDB数据库
  const initializeCzdb = async () => {
    const ipv4DbPath = process.env.CZDB_IPV4_PATH;
    const ipv6DbPath = process.env.CZDB_IPV6_PATH;
    const key = process.env.CZDB_KEY;

    if (!key) {
      console.error("错误: 缺少CZDB_KEY环境变量");
      process.exit(1);
    }

    try {
      // 检查数据库文件是否存在，不存在则下载
      if (!checkDatabaseFiles()) {
        console.log("数据库文件不存在，开始下载...");
        await updateCZDB();
        console.log("数据库文件下载完成");
      }

      const initialized = czdbService.initialize(ipv4DbPath, ipv6DbPath, key);
      if (initialized) {
        console.log("CZDB数据库初始化成功");
      } else {
        console.error("CZDB数据库初始化失败");
        process.exit(1);
      }
    } catch (error) {
      console.error("CZDB数据库初始化出错:", error);
      process.exit(1);
    }
  };

  // 在启动服务器之前初始化数据库
  (async () => {
    await initializeCzdb();
  })();

  // 设置定时任务，每天凌晨3点更新数据库
  let updateTask = cron.schedule(
    "0 3 * * *",
    async () => {
      console.log("开始执行CZDB数据库更新任务...");
      try {
        await updateCZDB();
        console.log("CZDB数据库更新任务完成");
      } catch (error) {
        console.error("CZDB数据库更新任务失败:", error);
        // 更新失败时尝试重新初始化现有数据库
        try {
          await initializeCzdb();
        } catch (initError) {
          console.error("重新初始化失败:", initError);
        }
      }
    },
    {
      scheduled: true,
      timezone: "Asia/Shanghai",
    }
  );

  // 优雅关闭处理
  process.on("SIGTERM", () => {
    console.log("收到 SIGTERM 信号，准备关闭服务...");
    updateTask.stop();
    czdbService.destroy();
    process.exit(0);
  });

  // 加载CZDB路由
  app.use("/api/czip", czdbRoutes);
} else {
  console.log("CZDB功能未启用");
}
process.on("SIGINT", () => {
  console.log("收到 SIGINT 信号，准备关闭服务...");
  updateTask.stop();
  czdbService.destroy();
  process.exit(0);
});

// ip2region路由
app.use("/api/ip", ipRoutes);

// 错误处理
app.use(errorHandler);

// 启动服务器
app.listen(port, () => {
  console.log(`服务器运行在 http://localhost:${port}`);
});
